#include <cmath>
#include "pega.h"
#include "mapa.h"
#include "timer.h"
#include <SDL/SDL_timer.h>


SDL_Event evento;                       // Usado para pegar eventos do teclado
jogador *Jogador;  						// Jogador

int Mapa_Atual = 0;
int Mapa_Proximo = 0;
Timer timer;

Mapa mapa;
Mapa interseccao;
Mapa fim;
int mapa_x = 30;
int mapa_y = 30;

int timerInicio;

// Gera uma posição em um lugar válido do mapa e a retorna

//posicao gerar_posicao()
//{
	//int x = 0;
	//int y = 0;
	//int zr = 0;
	//posicao pos;

	//zr = rand()%360;
	//pos.mudar_r(-90,zr);

	//do
	//{
		//x = rand()%mapa_x;
		//y = rand()%mapa_y;
	//}
	//while( Mapa[x][y] == 1 );

	//pos.mudar(20*x+5,20*y+5,5);

	//return pos;
//}

// Cria as paredes e o chão de acordo com a matriz mapa do nivel dado e guarda na
// lista de renderização número "numero"
void carregar_mapa( Mapa &m, int nivel, int numero )
{
	int i,j;
	posicao pos;

	// Céu
	pos.mudar_r(0,0);
	//pos.mudar(-100,-100,1000000);
	//new plano( pos, 20000, 8 );

	// Cria cada chão
	for( i=0; i<mapa_x; i++ )
	{
		for( j=0; j<mapa_y; j++ )
		{
			if( m(nivel,i,j) != 1 )
			{
				if ( m.fim[2] == nivel && m.fim[0] == i && m.fim[1] == j )
				{
					pos.mudar(20*i+10,20*j+10,20);
					new plano( pos, 20, 5, numero );
				}
				else
				{
					pos.mudar(20*i+10,20*j+10,0);
					new plano( pos, 20, 2, numero );
				}
			}
		}
	}

	// Cria cada teto
	for( i=0; i<mapa_x; i++ )
	{
		for( j=0; j<mapa_y; j++ )
		{
			if( m(nivel,i,j)!= 0 )
			{
				pos.mudar(20*i+10,20*j+10,20);
				new plano( pos, 20, 9, numero );
			}
		}
	}

	char vert[mapa_x][mapa_y-1];
	char hori[mapa_x-1][mapa_y];

	for( i=0; i<mapa_y; i++ )
	{
		for( j=0; j<mapa_x; j++ )
		{
			//Preenche matriz de paredes verticais
			if( j < mapa_x-1 )
			{
				if( m(nivel,i,j) == m(nivel,i,j+1) )
				{
					vert[i][j] = 0;
				}
				else
				{
					vert[i][j] = 1;
				}
			}
			//Preenche matriz de paredes horizontais
			if( i < mapa_y-1 )
			{
				if( m(nivel,i,j) == m(nivel,i+1,j) )
				{
					hori[i][j] = 0;
				}
				else
				{
					hori[i][j] = 1;
				}
			}
		}
	}

	//Cria as paredes verticais
	pos.mudar_r(-90,0);
	for( i=0; i<mapa_y; i++ )
	{
		for( j=0; j<mapa_x-1; j++ )
		{
			if( vert[i][j] == 1 )
			{
				pos.mudar(20*i+10,20*j+20,10);
				new plano( pos, 20, 1, numero );
			}
		}
	}

	//Cria as paredes horizontais
	pos.mudar_r(-90,90);
	for( i=0; i<mapa_y-1; i++ )
	{
		for( j=0; j<mapa_x; j++ )
		{
			if( hori[i][j] == 1 )
			{
				pos.mudar( (20*i+20), (20*j+10),10);
				new plano( pos, 20, 1, numero );
			}
		}
	}

	//Bordas do mapa
	pos.mudar_r(-90,90);
	for( i=0; i<mapa_y; i++ )
	{
		pos.mudar( 0, i*20+10,10);
		new plano( pos, 20, 1, numero );
	}
	for( i=0; i<mapa_y; i++ )
	{
		pos.mudar( mapa_x*20, i*20+10,10);
		new plano( pos, 20, 1, numero );
	}
	pos.mudar_r(-90,0);
    for( i=0; i<mapa_x; i++ )
    {
        pos.mudar( i*20+10, 0,10);
        new plano( pos, 20, 1, numero );
    }
	for( i=0; i<mapa_x; i++ )
	{
		pos.mudar( i*20+10, mapa_y*20,10);
		new plano( pos, 20, 1, numero );
	}
}

/*monta as listas da intersecção dos mapas*/
void carregar_inter( Mapa &m, int nivel, int numero )
{
	posicao pos;
	// Céu
	pos.mudar_r(0,0);

	/*cria as listas de intersecção de tudo*/
	for (int i=0 ; i<DIMENSAO ; i++)
	{
		for (int j=0 ; j<DIMENSAO ; j++)
		{
			if ( m(nivel,i,j) == 1)
			{
				pos.mudar(20*i+10,20*j+10,0);
				new plano( pos, 20, 6, numero );
			}
		}
	}
}


void jogador::mover( float x, float y, float z )
{
	int x2, y2;
	posicao pos2;
	pos2.igualar(pos);
	pos2.adicionar( 20*x, 20*y, 20*z );
	x2 = (int)(pos2.x/20);
	y2 = (int)(pos2.y/20);

	//printf("A( %f , %f ) ( %d , %d )\n",(pos2.x/20),(pos2.y/20),x2,y2 );
	if( x2 < mapa_x && pos2.x >= 0 && y2 < mapa_y && pos2.y >= 0 && mapa(Mapa_Atual,x2,y2) != 1 )
	{
		pos.adicionar( 20*x, 20*y, 20*z );
	}
	//printf("D( %f , %f )\n",(pos.x/20),(pos.y/20) );
}

int jogo()
{
	Uint8 *keystates;
	int var = 0;
	float t=0;
	bool trocandoFase;

	// Liga a biblioteca gráfica
	acender_fogo(10);

	carregar_textura("jogador.tga",4);
	carregar_textura("parede.tga",1);
	carregar_textura("chao.tga",2);
	carregar_textura("fim.tga",5);
	carregar_textura("nao.tga",6);

	/*carrega os arquivos de mapas*/
    mapa.carrega("mapa.txt");
	/*aloca espaço pras intersecções*/
	interseccao.aloca(mapa.numNiveis);
	/*a tela de "fim" também é um mapa!*/
	fim.carrega("fim.txt");
	/*monta a intersecção de cada um dos níveis*/
	for (int i=0 ; i<mapa.numNiveis ; i++)
	{
		/*testa caaada um dos quadrados*/
		for (int j=0 ; j<DIMENSAO ; j++)
		{
			for (int k=0 ; k<DIMENSAO ; k++)
			{
				
				if (i == mapa.numNiveis - 1) /*último andar.. tratar isso*/
				{
					/*vê se algum quadrado livre será ocupado no próximo estágio*/
					if ( mapa(i, j, k) == 0 && mapa(0, j, k) == 1 )
						interseccao(i, j, k) = 1;
					else
						interseccao(i, j, k) = 0;
				}
				else
				{
					/*testa se o quadrado é ocupado no mapa a seguir*/
					if ( mapa(i, j, k) == 0 && mapa(i+1, j, k) == 1 )
						interseccao(i, j, k) = 1;
					else
						interseccao(i, j, k) = 0;
				}
			}
		}
	}

	/*carrega os mapas de verdade*/
	for (int i=0 ; i<mapa.numNiveis ; i++)
		carregar_mapa(mapa, i,i+1);
	/*carrega as intersecções*/
	for (int i=0 ; i<mapa.numNiveis ; i++)
		carregar_inter(interseccao, i, i+1+mapa.numNiveis);
    /*carrega o fim*/
    carregar_mapa(fim, 0, mapa.numNiveis+1+mapa.numNiveis);
	//Inicia o jogador
	posicao pos;
	pos.mudar(10 + (mapa.inicio[0])*20,10+ (mapa.inicio[1])*20,10);
	pos.mudar_r(0,0);
	Jogador = new jogador(pos,20,4,0);

	// Posiciona a câmera no topo do mapa
    cam.pos.mudar_r(-90,0);
    cam.pos.mudar(300,300,750);

	/*Seta o mapa atual pro mapa de início e o próximo pro próximo da sequencia*/
	/*se o proximo não existir, volta pro primeiro*/
	Mapa_Atual = mapa.inicio[2];
	if (mapa.numNiveis - 1 == Mapa_Atual)
		Mapa_Proximo = 0;
	else
		Mapa_Proximo = Mapa_Atual + 1;

	trocandoFase = false;
	//-----------------------------------------------

	printf(" ( Iniciando loop principal do jogo ) \n");
	var = 0;
	while( var == 0 )
	{
		while( SDL_PollEvent( &evento ) )
		{
			if( evento.type == SDL_QUIT )
			{
				var = -1;
			}
			if( evento.type == SDL_KEYDOWN )
			{
				if( evento.key.keysym.sym == SDLK_ESCAPE ){var = -1;}
			}
		}

		// Essa parte detecta as teclas q o jogador apertou
		keystates = SDL_GetKeyState( NULL );
		// Caso ele esteja com C apartado, mova apenas a câmera
		if( keystates[ SDLK_c ] )
		{
			if( keystates[ SDLK_UP ] ){cam.mover(0,1,0);}
			if( keystates[ SDLK_DOWN ] ){cam.mover(0,-1,0);}
			if( keystates[ SDLK_LEFT ] ){cam.mover(-1,0,0);}
			if( keystates[ SDLK_RIGHT ] ){cam.mover(1,0,0);}
			if( keystates[ SDLK_PAGEUP ] ){cam.mover(0,0,1);}
			if( keystates[ SDLK_PAGEDOWN ] ){cam.mover(0,0,-1);}

			if( keystates[ SDLK_a ] ){cam.rodar(0,-1);}
			if( keystates[ SDLK_d ] ){cam.rodar(0,1);}
			if( keystates[ SDLK_w ] ){cam.rodar(1,0);}
			if( keystates[ SDLK_s ] ){cam.rodar(-1,0);}
		}
		// Caso contrário move o personagem
		else
		{
			if( keystates[ SDLK_UP ] ){Jogador->mover(0,1,0);}
			if( keystates[ SDLK_DOWN ] ){Jogador->mover(0,-1,0);}
			if( keystates[ SDLK_LEFT ] ){Jogador->mover(-1,0,0);}
			if( keystates[ SDLK_RIGHT ] ){Jogador->mover(1,0,0);}
			if( keystates[ SDLK_PAGEUP ] ){Jogador->mover(0,0,1);}
			if( keystates[ SDLK_PAGEDOWN ] ){Jogador->mover(0,0,-1);}

			if( keystates[ SDLK_a ] ){Jogador->rodar(0,1);}
			if( keystates[ SDLK_d ] ){Jogador->rodar(0,-1);}
			if( keystates[ SDLK_w ] ){Jogador->rodar(1,0);}
			if( keystates[ SDLK_s ] ){Jogador->rodar(-1,0);}

			//cam.pos2.mudar_r(0,Jogadores[Meu_Num]->pos.zr);
		}

		if (timer.passou(4000)) /*aviso que vai trocar o nível*/
		{
			trocandoFase = true;
			if (timer.passou(5000)) /*vai trocar. Do nada mesmo. Tá embaixo? MORREU!!*/
			{
				/*seta o proximo mapa e o atual*/
				Mapa_Atual = Mapa_Proximo;
				if (Mapa_Atual == mapa.numNiveis - 1)
					Mapa_Proximo = 0;
				else
					Mapa_Proximo += 1;

				/*zera o timer*/
				timer.seta();
				trocandoFase = false;
			}
		}

		/*viu, ele chegou no fim..*/
		if (Mapa_Atual == mapa.fim[2] &&
			Jogador->pos.x == mapa.fim[0]*20 + 10 &&
			Jogador->pos.y == mapa.fim[1]*20 + 10 )
		{
			/*loop basico de eventos..*/
			while(var == 0)
			{
			    while( SDL_PollEvent( &evento ) )
                {
                    if( evento.type == SDL_QUIT )
                    {
                        var = -1;
                    }
                    if( evento.type == SDL_KEYDOWN )
                    {
                        if( evento.key.keysym.sym == SDLK_ESCAPE ){var = -1;}
                    }
                }
                desenhar_listas_inicio();
                desenhar_lista(mapa.numNiveis+mapa.numNiveis+1,0,0,0);
                desenhar_listas_fim();
                SDL_Delay(10);
            }
            /*MEGAHACK*/
            /*ganhou, saiu, acabou*/
            exit(0);
		}
        desenhar_listas_inicio();
		desenhar_lista(Mapa_Atual+1,0,0,0);
		if (trocandoFase)
		{
			/*desenha intersecção*/
			desenhar_lista(Mapa_Atual+mapa.numNiveis+1,0,0,0);
		}
		desenhar_lista(0,0,0,10);
		desenhar_listas_fim();

		t++;
		if(t>10000)t=0;
	}

	// Desliga a biblioteca gráfica
	apagar_fogo();

	printf("\n ( Jogo encerrado ) \n\n");

	return 1;
}

/*SDL no windows requer link pra C, não C++*/
extern "C" {
    int main(int argc, char *argv[])
    {
        srand(time (0));

        printf(" ____________ \n");
        printf("|            |\n");
        printf("| MULTI LABS |\n");
        printf("|____________|\n\n");

        printf(" ( Iniciando jogo ) \n");
        timerInicio = SDL_GetTicks();
        jogo();

        return 1;
    }
}

